#####################################################################
# Product:      KnowledgeEngine (Plone Edition)
#
# File:         PloneUserProviderService.py
#
# Copyright:    Copyright (c) 2004, Faulkner Technologies
#
# Author:       Brian Oliver
#
# Description:  Defines an abstract service that is used to provide
#               the KnowledgeEngine internal security model with
#               'User' instances.
#
#               This service provides a layer of protection over
#               User management.  For example, implementations of this
#               service may include; Zope ACL User Folders, Plone
#               User Folders, MySQL or LDAP implementations.
#
#               This service does not in general provide the ability
#               to create users as this is often implementation
#               dependant.
#
# See Also:     Service, User, Group, GroupProviderService
#####################################################################

#####################################################################
## KnowledgeEngine Library Imports
from Products.KnowledgeEngine.Common import *
from Products.KnowledgeEngine.Core import *
from Products.KnowledgeEngine.UserProviderService import UserProviderServiceInfo, UserProviderService
from Products.KnowledgeEngine.User import User

#####################################################################
## Zope Library Imports
# (none)
from Products.CMFCore.utils import getToolByName

#####################################################################
## Python Library Imports
# (none)

#####################################################################
## PloneUserProviderService Class Definition
class PloneUserProviderServiceInfo(UserProviderServiceInfo):
    """
        Defines the the user provider service meta-information
    """

    #---------------------------------------------------------------#

    def getClassName(self):
        """
            Returns the name of the class for which
            we are providing information.
        """
        return 'PloneUserProviderService'


    #---------------------------------------------------------------#

    def getDisplayName(self):
        """
            Return a friendly name for the class instances
            (this is used for displaying in lists etc)
        """

        return "KnowledgeEngine: Plone User Provider Service"

    #---------------------------------------------------------------#

    def getServiceName(self):
        """
            ABSTRACT: Return the lookup-identity.

            This method must be overriden to provide a unique service name
            (this name is used to set the zope id of the service
            when created)
        """

        return "knowledgeengine_userproviderservice"

#####################################################################
## PloneUserProviderService Class Definition
class PloneUserProviderService(UserProviderService):
    """
        Defines a tool that may be used to manage Knowledge Engine
        users
    """

    #---------------------------------------------------------------#

    #ABSTRACT TRANSIENT: a ServiceInfo implementation instance to provide info about this service
    _SERVICEINFO = PloneUserProviderServiceInfo()

    #---------------------------------------------------------------#

    def __init__(self):
        """
            Constructor for the object
        """

        #this is a stateless mix-in
        pass

    #---------------------------------------------------------------#

    def getUser(self, userIdentity):
        """
            Returns a Knowledge Engine User instance for the
            user with the provided identity.

            The userIdentity is a unique string that identifies the user
            with for the service implementation.  Typically this is
            the user login name (but is actually implementation dependant)

            Returns None if the user is unknown.

            RETURN TYPE: User
        """

        #handle if the userIdentity provided is None (this means the anonymous user)
        userIdentity = iif(userIdentity is None, "anonymous", userIdentity)

        #ensure the identity is a string
        user = None
        if userIdentity == 'anonymous':
            user = User(userIdentity, userIdentity, "")
        else:
            #get the plone membership tool
            ploneMembershipTool = getToolByName(self, 'portal_membership');

            #get the plone member
            member = ploneMembershipTool.getMemberById(userIdentity)

            #is the user a portal member?
            if member is not None:
                #create a knowledge engine user for the plone member
                fullname = member.getProperty("fullname", "")
                if fullname == "":
                    fullname = userIdentity
                user = User(userIdentity, fullname, member.getProperty("email", ""))
                
            #not known as a plone member                
            else:
                #attempt to find the acluser folder containing the user Identity
                try:
                    aclUserHome = ploneMembershipTool._findUsersAclHome(userIdentity)
                    aclUser = aclUserHome.getUser(userIdentity)

                    #does the user exist?                
                    if aclUser is not None:
                        user = User(userIdentity, aclUser.name, "")

                    #unknown user!                
                    else:            
                        user = None
                except:
                    #some error... so we assume the user doesn't exist
                    user = None
                    
        return user

    #---------------------------------------------------------------#

    def getUsers(self, includeAnonymousUser = false):
        """
            Returns a list of the available Users
            from the service implementation

            RETURN TYPE: [User]
        """

        #get the plone membership tool
        ploneMembershipTool = getToolByName(self, 'portal_membership');

        #create knowledge engine users for each plone user
        users = []
        for member in ploneMembershipTool.listMembers():
            users = users + [User(member.getId(), member.getProperty("fullname", member.getId()), member.getProperty("email", ""))]

        #include the anonymous user?
        if includeAnonymousUser:
            users = [User('anonymous', '(anonymous user)', '')] + users

        return users

    #---------------------------------------------------------------#

    def searchUsers(self, searchString):
        """
            Returns a UserIterator over the Users 
            matching a string query against id and full name
            
            RETURN TYPE: [User]
        """

        #get the plone membership tool
        ploneMembershipTool = getToolByName(self, 'portal_membership');
        
        users = []
        userids = []
        
        if searchString:
            for user in ploneMembershipTool.searchForMembers(REQUEST=None, getId=searchString):
                userids.append(user.getId())
                users = users + [User(user.getId(), user.getProperty("fullname", user.getId()), user.getProperty("email", ""))]
            for user in ploneMembershipTool.searchForMembers(REQUEST=None, getFullName=searchString):
                if user.getId() not in userids:
                    users = users + [User(user.getId(), user.getProperty("fullname", user.getId()), user.getProperty("email", ""))]

        return users
        
    #---------------------------------------------------------------#  
    
#####################################################################
## Class Initialisation

# Register Service Information with the Knowledge Engine
registerServiceClass(PloneUserProviderService)